/*
 * Gedigarr - Falling block game.
 * Copyright (C) 2010  BoredCorp
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */
package gedigarr.resources;

import java.awt.Font;
import java.awt.FontFormatException;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;

/**
 *
 * @author Jonathan Coyle
 */
public class ResourceManager {

  public final static int LOC_FS = 0x00;
  public final static int LOC_JAR = 0x01;
  public final static int TYPE_UNKNOWN = 0x10;
  public final static int TYPE_IMAGE = 0x11;
  public final static int TYPE_FILE = 0x12;
  public final static int TYPE_FONT = 0x13;
  public final static int ACCESS_READONLY = 0x20;
  public final static int ACCESS_WRITABLE = 0x21;
  private static ResourceManager self = null;
  private HashMap<String, GameResource> jarResources;
  private HashMap<String, GameResource> fsResources;

  private ResourceManager() {
    jarResources = new HashMap<String, GameResource>();
    fsResources = new HashMap<String, GameResource>();
  }

  public static ResourceManager getInstance() {
    if ( self == null ) {
      self = new ResourceManager();
    }
    return self;
  }

  private File getFile( String resource ) {
    File f = null;
    f = new File( resource );
    return f;
  }

  private InputStream getStream( String resource ) throws IOException {
    URL erl = ResourceManager.class.getClassLoader().getResource( resource );
    return erl == null ? null : erl.openStream();
  }

  private BufferedImage getImageFromJar( String resource ) throws IOException {
    //String rString = resource.getString();
    InputStream is = getStream( resource );
    // if is is null, bi = null, otherwise do the ImageIO read.
    BufferedImage bi = is == null ? null : ImageIO.read( is );

    return bi;
  }
  
  private Font getFontFromJar( String resource ) {
    Font f  = null;
    InputStream is = null;
    try {
      is = getStream( resource );
      f = Font.createFont( Font.TRUETYPE_FONT, is );
    } catch ( FontFormatException ex ) {
      Logger.getLogger( ResourceManager.class.getName() ).log( Level.SEVERE, null, ex );
    } catch ( IOException ex ) {
      Logger.getLogger( ResourceManager.class.getName() ).log( Level.SEVERE, null, ex );
    }
    return f;
  }

  private BufferedImage getImage( String resource ) throws IOException {
    File f = new File( resource );
    BufferedImage bi = ImageIO.read( f );
    return bi;
  }

  public GameResource<BufferedImage> readImage( String resource, int loc ) {
    BufferedImage bi = null;
    GameResource gr = null;
    try {
      switch ( loc ) {
        case LOC_FS:
          if ( fsResources.containsKey( resource ) ) {
            gr = fsResources.get( resource );
          } else {
            gr = new GameResource( resource, loc, TYPE_IMAGE, ACCESS_READONLY );
            bi = getImage( resource );
            gr.setResource( bi );
            fsResources.put( resource, gr );
          }
          break;
        case LOC_JAR:
          if ( jarResources.containsKey( resource ) ) {
            gr = jarResources.get( resource );
          } else {
            gr = new GameResource( resource, loc, TYPE_IMAGE, ACCESS_READONLY );
            bi = getImageFromJar( resource );
            gr.setResource( bi );
            jarResources.put( resource, gr );
          }
          break;
      }
    } catch ( IOException ex ) {
      Logger.getLogger( ResourceManager.class.getName() ).log( Level.SEVERE, null, ex );
    }

    return gr;
  }

  public GameResource<Font> loadFont( String resource, int loc ) {
    GameResource<Font> gr = null;
    Font f = null;
    switch ( loc ) {
      case LOC_JAR:
        //fsResources.
          if ( jarResources.containsKey( resource ) ) {
            gr = jarResources.get( resource );
          } else {
            gr = new GameResource<Font>( resource, loc, TYPE_FONT, ACCESS_READONLY );
            f = getFontFromJar( resource );
            gr.setResource( f );
            putJar( resource, gr );
          }
        break;
    }
    return gr;
  }

  public GameResource<File> retrieveFile( String resource, int loc, int access ) {
    GameResource<File> gr = null;
    File f = null;
    
    switch ( loc ) {
      case LOC_FS:
        //fsResources.
          if ( fsResources.containsKey( resource ) ) {
            gr = fsResources.get( resource );
          } else {
            gr = new GameResource( resource, loc, TYPE_FILE, access );
            f = getFile( resource );
            gr.setResource( f );
            putFs( resource, gr );
          }
        break;
    }
    return gr;
  }

  public void putJar( String rString, GameResource resource ) {
    jarResources.put( rString, resource );
  }

  public void putFs( String rString, GameResource resource ) {
    fsResources.put( rString, resource );
  }
}
